package com.css.fxfzypg.modules.baseData.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.css.fxfzypg.base.response.RestResponse;
import com.css.fxfzypg.common.utils.CheckObjFields;
import com.css.fxfzypg.common.utils.UpdateUtil;
import com.css.fxfzypg.common.utils.excel.ExcelReaderUtil;
import com.css.fxfzypg.common.utils.excel.ExcelResult;
import com.css.fxfzypg.constants.FxfzConstants;
import com.css.fxfzypg.constants.YNEnum;
import com.css.fxfzypg.modules.baseData.queryParams.HosPeoQueryParams;
import com.css.fxfzypg.modules.baseData.repository.HosPeoRepository;
import com.css.fxfzypg.modules.baseData.entity.HosPeoEntity;
import com.css.fxfzypg.modules.baseData.service.HosPeoService;
import com.css.fxfzypg.util.*;
import com.css.fxfzypg.zcpt.sys.service.SysAreaService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author y1fan
 * @create 2022-08-23 12:07
 */
@Service
@Slf4j
public class HosPeoServiceImpl implements HosPeoService {
    @Resource
    private HosPeoRepository hosPeoRepository;
    @Resource
    private SysAreaService sysAreaService;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    /**
     * 保存
     *
     * @param entity 人口和建筑物概况实体
     * @return 响应信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse saveHosPeo(HosPeoEntity entity) {
        Map<String, String> areaIdCodeMap = (Map<String, String>) JSONObject.parse(redisTemplate.opsForValue().get(FxfzConstants.CACHE_SYS_KEY + "areaIdCodeMap"));
        HosPeoEntity hosPeoEntity = hosPeoRepository.fingHosPeoBydivision(entity.getProvinceId(), entity.getCityId(), entity.getPrefectureId());
        if (hosPeoEntity != null) {
            return RestResponse.fail("该省市县已存在，请去修改！！");
        }
        entity.setDhpId(UUIDGenerator.getUUID());
        String divisionNames = null;
        try {
            //根据省市县Id,获取省市县名称;单个id可以获得单个名称;多个id，用逗号分割，可以获得多个名称
            String divisionIds = entity.getProvinceId() + "," + entity.getCityId() + "," + entity.getPrefectureId();
            divisionNames = sysAreaService.getAreaNameByAreaId(divisionIds);
        } catch (Exception e) {
            return RestResponse.fail("省市县的id不符合符合规范！");
        }
        String[] split = divisionNames.split(",");
        entity.setProvince(split[0]);
        if (split.length == 2) {
            entity.setCity(split[0]);
            entity.setPrefecture(split[1]);
        } else {
            entity.setCity(split[1]);
            entity.setPrefecture(split[2]);
        }
        StringBuilder message = getMessage(entity);
        entity.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        entity.setCreateUser(PlatformSessionUtils.getUserId());
        entity.setIsDelete(YNEnum.N.toString());
        entity.setProvinceCode(areaIdCodeMap.get(entity.getProvinceId()));
        entity.setCityCode(areaIdCodeMap.get(entity.getCityId()));
        entity.setPrefectureCode(areaIdCodeMap.get(entity.getPrefectureId()));
        if (message.length() < 1) {
            int i = hosPeoRepository.saveHosPeo(entity);
            return ResponseCreator.createSuccessResponse(null, "保存成功！");
        }
        return RestResponse.fail(String.valueOf(message));
    }

    /**
     * 根据id查询单条数据
     *
     * @param id 实体id:dhpId
     * @return
     */
    @Override
    public HosPeoEntity fingHosPeoById(String id) {
        return hosPeoRepository.fingHosPeoById(id);
    }

    /**
     * 修改
     *
     * @param hosPeoEntity 人口和建筑物概况实体
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RestResponse updateHosPeo(HosPeoEntity hosPeoEntity) {
        StringBuilder message = getMessage(hosPeoEntity);
        if (message.length() > 0) {
            return RestResponse.fail(String.valueOf(message));
        }
        HosPeoEntity hosPeoEntity1 = hosPeoRepository.fingHosPeoById(hosPeoEntity.getDhpId());
        UpdateUtil.copyNullProperties(hosPeoEntity1, hosPeoEntity);
        hosPeoEntity.setUpdateUser(PlatformSessionUtils.getUserId());
        hosPeoEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
        int i = hosPeoRepository.updateHosPeo(hosPeoEntity);
        return ResponseCreator.createSuccessResponse(null, "修改成功！");
    }

    /**
     * 根据条件分页查询
     *
     * @param queryParams 分页查询的条件
     * @param curPage     第几页
     * @param pageSize    一页多少条
     * @return JSONObject
     * jsonObject.put("rows" , page.getContent()); 数据
     * jsonObject.put("total" ,page.getTotalElements()); 数据总条数
     */
    @Override
    public JSONObject getAllHosPeoByParams(HosPeoQueryParams queryParams, int curPage, int pageSize) {
        return hosPeoRepository.getAllHosPerByParams(queryParams, curPage, pageSize);

    }

    /**
     * 逻辑删除
     *
     * @param id 实体id:dhpId
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteHosPeo(String id) {
        String userId = PlatformSessionUtils.getUserId();
        Timestamp currentTimestamp = PlatformDateUtils.getCurrentTimestamp();
        hosPeoRepository.deleteHosPeo(id, userId, currentTimestamp);
    }

    /**
     * 对实体类数据进行校验
     *
     * @param entity 实体类
     * @return 错误信息
     */
    private StringBuilder getMessage(HosPeoEntity entity) {
        StringBuilder message = new StringBuilder();
        if (PlatformObjectUtils.isEmpty(entity.getDhpCountyArea())) {
            message.append("区县面积（km2）不能为空！ ");
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpTotalPop())) {
            message.append("总人口（（万）不能为空！ ");
        }
        BigDecimal dhpRatio = entity.getDhpYoungRatio().add(entity.getDhpMiddleRatio()).add(entity.getDhpOldTatio());
        if (dhpRatio.compareTo(BigDecimal.valueOf(100)) != 0 && dhpRatio.compareTo(BigDecimal.ZERO) != 0) {
            message.append("人口比例%不合规范！ ");
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpHouseTatio())) {
            message.append("住宅房屋占比（%）不能为空！ ");
        } else {
            if (entity.getDhpHouseTatio().compareTo(BigDecimal.ZERO) < 0 || entity.getDhpHouseTatio().compareTo(BigDecimal.valueOf(100)) > 0) {
                message.append("住宅房屋占比（%）不合规范！ ");
            }
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpTownTatio())) {
            message.append("城镇地区建筑占总体建筑物的比例（%）不能为空！ ");
        } else {
            if (entity.getDhpTownTatio().compareTo(BigDecimal.ZERO) < 0 || entity.getDhpTownTatio().compareTo(BigDecimal.valueOf(100)) > 0) {
                message.append("城镇地区建筑占总体建筑物的比例（%）不合规范！ ");
            }
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpTownHighTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownSteelTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownBetonTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownBrickTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownMasonryTatio()) ||
                PlatformObjectUtils.isEmpty(entity.getDhpTownSoilTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownWoodTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownStoneTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpTownOtherTatio())) {
            message.append("城镇地区结构类型占比（%）不能为空！ ");
        } else {
            BigDecimal dhpTownTatio = entity.getDhpTownHighTatio().add(entity.getDhpTownSteelTatio()).add(entity.getDhpTownBetonTatio()).add(entity.getDhpTownBrickTatio()).add(
                    entity.getDhpTownMasonryTatio()).add(entity.getDhpTownSoilTatio()).add(entity.getDhpTownWoodTatio()).add(entity.getDhpTownStoneTatio()).add(entity.getDhpTownOtherTatio());
            if (dhpTownTatio.compareTo(BigDecimal.valueOf(100)) != 0) {
                message.append("城镇地区结构类型占比（%）不合规范！ ");
            }
        }
        BigDecimal dhpTownTatio = entity.getDhpTownSevenBeforeTatio()
                .add(entity.getDhpTownSevenTatio())
                .add(entity.getDhpTownEightTatio())
                .add(entity.getDhpTownNineTatio())
                .add(entity.getDhpTownZeroTatio())
                .add(entity.getDhpTownTenTatio())
                .add(entity.getDhpTownSixteenTatio())
                .add(entity.getDhpTownTwentyOneTatio());
        if (dhpTownTatio.compareTo(BigDecimal.valueOf(100)) != 0 && dhpTownTatio.compareTo(BigDecimal.ZERO) != 0) {
            message.append("城镇地区年代类型占比%不合规范！ ");
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpTownIndoorProperty())) {
            message.append("城镇地区室内财产（元/每平米）不能为空！ ");
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpVillageHighTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageSteelTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageBetonTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageBrickTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageMasonryTatio()) ||
                PlatformObjectUtils.isEmpty(entity.getDhpVillageSoilTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageWoodTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageStoneTatio()) || PlatformObjectUtils.isEmpty(entity.getDhpVillageOtherTatio())) {
            message.append("农村地区结构类型占比（%）不能为空！ ");
        } else {
            BigDecimal dhpVillageTatio = entity.getDhpVillageHighTatio().add(entity.getDhpVillageSteelTatio()).add(entity.getDhpVillageBetonTatio()).add(entity.getDhpVillageBrickTatio())
                    .add(entity.getDhpVillageMasonryTatio()).add(entity.getDhpVillageSoilTatio()).add(entity.getDhpVillageWoodTatio()).add(entity.getDhpVillageStoneTatio()).add(entity.getDhpVillageOtherTatio());
            if (dhpVillageTatio.compareTo(BigDecimal.valueOf(100)) != 0) {
                message.append("农村地区结构类型占比（%）不合规范！ ");
            }
        }
        BigDecimal dhpVillageTatio = entity.getDhpVillage1980Before()
                .add(entity.getDhpVillage8190Tatio())
                .add(entity.getDhpVillage9100Tatio())
                .add(entity.getDhpVillage0110Tatio())
                .add(entity.getDhpVillage1115Tatio())
                .add(entity.getDhpVillage1620Tatio())
                .add(entity.getDhpVillage21AfterTatio());
        if (dhpVillageTatio.compareTo(BigDecimal.valueOf(100)) != 0 && dhpVillageTatio.compareTo(BigDecimal.ZERO) != 0) {
            message.append("农村地区年代类型占比%不合规范！ ");
        }
        if (PlatformObjectUtils.isEmpty(entity.getDhpVillageIndoorProperty())) {
            message.append("农村地区室内财产（元/每平米）不能为空！ ");
        }

        return message;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void exportExcel(HttpServletResponse response) throws IOException {
        List<HosPeoEntity> list = hosPeoRepository.exportExcel();
        FileUtil.exportExcel(list, "人口和建筑物概况数据表", "sheet", HosPeoEntity.class, "HosPeoExcel", response);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importExcel(MultipartFile file) throws IOException {
        Map<String, String> areaIdCodeMap = (Map<String, String>) JSONObject.parse(redisTemplate.opsForValue().get(FxfzConstants.CACHE_SYS_KEY + "areaIdCodeMap"));
        List<HosPeoEntity> hosPeoEntities = FileUtil.importExcel(file, 0, 1, HosPeoEntity.class);
        for (HosPeoEntity hosPeoEntity : hosPeoEntities) {
            if (CheckObjFields.isAllFieldNull(hosPeoEntity)) {
                continue;
            }
            String divisionIds = "";

            //判断省市县的名称是否符合规范
            divisionIds = sysAreaService.getIdByCondition(URLEncoder.encode(hosPeoEntity.getProvince(), "utf-8"),
                    URLEncoder.encode(hosPeoEntity.getCity(), "utf-8"),
                    URLEncoder.encode(hosPeoEntity.getPrefecture(), "utf-8"));
            if (StringUtils.isBlank(divisionIds) || divisionIds.split("_").length < 3) {
                throw new RuntimeException("导入失败，请检查" + hosPeoEntity.getProvince() + "," + hosPeoEntity.getCity() + "," + hosPeoEntity.getPrefecture() + "数据正确性");
            }
            hosPeoEntity.setDhpId(UUIDGenerator.getUUID());
            hosPeoEntity.setUpdateTime(PlatformDateUtils.getCurrentTimestamp());
            hosPeoEntity.setIsDelete(YNEnum.N.toString());
            hosPeoEntity.setProvinceCode(areaIdCodeMap.get(hosPeoEntity.getProvinceId()));
            hosPeoEntity.setCityCode(areaIdCodeMap.get(hosPeoEntity.getCityId()));
            hosPeoEntity.setPrefectureCode(areaIdCodeMap.get(hosPeoEntity.getPrefectureId()));
        }
        hosPeoRepository.importExcel(hosPeoEntities);
    }

    @Override
    public RestResponse hosPeoImportExcel(MultipartFile file) throws Exception {
        List<HosPeoEntity> entityList = new ArrayList<>();
        ExcelResult excelResult = ExcelReaderUtil.readExcel2Bean(file.getInputStream(), HosPeoEntity.class);
        StringBuilder message = new StringBuilder(excelResult.getMessage());
        if (excelResult.getData().size() == 0) {
            return ResponseCreator.createSuccessResponse(null, message.toString());
        }
        for (Object datum : excelResult.getData()) {
            HosPeoEntity entity = (HosPeoEntity) datum;
            String divisionIds = null;
            try {
                //判断省市县的名称是否符合规范
                divisionIds = sysAreaService.getIdByCondition(URLEncoder.encode(entity.getProvince(), "utf-8"),
                        URLEncoder.encode(entity.getCity(), "utf-8"),
                        URLEncoder.encode(entity.getPrefecture(), "utf-8"));
            } catch (Exception e) {
                message.append(entity.getProvince() + "," + entity.getCity() + "," + entity.getPrefecture() + " 省市县的名称不规范.<br/>");
                continue;
            }
            String[] s = divisionIds.split("_");
            if (s.length != 3) {
                message.append(entity.getProvince() + "," + entity.getCity() + "," + entity.getPrefecture() + " 省市县的名称不规范.<br/>");
                continue;
            }
            entityList.add(entity);
        }
        if (entityList.size() == 0) {
            return ResponseCreator.createSuccessResponse(null, message.toString());
        }
        if (message.toString().length() > 0) {
            return ResponseCreator.createSuccessResponse(null, message.toString());
        }


        //所有数据都没有问题 开始校验需不需要覆盖
        for (HosPeoEntity hosPeoEntity : entityList) {
            //根据省市区查数据库
            HosPeoEntity hosPeo = hosPeoRepository.findHosPeo(hosPeoEntity.getProvince(), hosPeoEntity.getCity(), hosPeoEntity.getPrefecture());
            if (hosPeo != null) {
                message.append(hosPeo.getProvince() + "," + hosPeo.getCity() + "," + hosPeo.getPrefecture() + " 该省市区下已有数据,确认是否需要覆盖<br/>");
            }
        }
        if (message.toString().length() > 0) {
            return ResponseCreator.createSuccessResponse(entityList, message.toString());
        }
        for (HosPeoEntity entity : entityList) {
            save(entity);
        }
        return ResponseCreator.createSuccessResponse(null, "成功导入" + entityList.size() + "条.");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cover(List<HosPeoEntity> hosPeoEntities) {
        for (HosPeoEntity hosPeoEntity : hosPeoEntities) {
            //根据省市区删除
            hosPeoRepository.delete(hosPeoEntity);
            save(hosPeoEntity);
        }
    }

    @Override
    public Integer countByCounty(String province, String city, String county) {
        return hosPeoRepository.countByCounty(province, city, county);
    }

    @Override
    public Integer countByCity(String province, String city) {
        return hosPeoRepository.countByCity(province, city);
    }

    @Override
    public Integer countByProvince(String name) {
        return hosPeoRepository.countByProvince(name);
    }

    private void save(HosPeoEntity entity) {
        String divisionIds = null;
        try {
            divisionIds = sysAreaService.getIdByCondition(URLEncoder.encode(entity.getProvince(), "utf-8"),
                    URLEncoder.encode(entity.getCity(), "utf-8"),
                    URLEncoder.encode(entity.getPrefecture(), "utf-8"));
            String[] split = divisionIds.split("_");
            entity.setProvinceId(split[0]);
            entity.setCityId(split[1]);
            entity.setPrefectureId(split[2]);
        } catch (UnsupportedEncodingException e) {
            log.info(e.getMessage());
        }
        entity.setIsDelete(YNEnum.N.toString());
        entity.setCreateUser(PlatformSessionUtils.getUserId());
        entity.setCreateTime(PlatformDateUtils.getCurrentTimestamp());
        try {
            Map<String, String> areaIdCodeMap = (Map<String, String>) JSONObject.parse(redisTemplate.opsForValue().get(FxfzConstants.CACHE_SYS_KEY + "areaIdCodeMap"));
            entity.setProvinceCode(areaIdCodeMap.get(entity.getProvinceId()));
            entity.setCityCode(areaIdCodeMap.get(entity.getCityId()));
            entity.setPrefectureCode(areaIdCodeMap.get(entity.getPrefectureId()));
        } catch (Exception e) {
            log.info("获取省市区code码错误");
        }
        entity.setDhpId(UUIDGenerator.getUUID());
        hosPeoRepository.saveHosPeo(entity);
    }
}
